﻿using System;
using Heaven.Geometry;
using Heaven.Mathematics;
using Heaven.Texturing;

namespace Heaven.Graphics
{
    /// <summary>
    /// Данный интерфейс предоставляет всю функциональность 
    /// типичного рендера (Microsoft DirectX®, OpenGL). 
    /// Естественно, что функциональность не может одинаково 
    /// подходить ко всем различным рендерам, поэтому 
    /// предоставляется интерфейс функциональности наиболее 
    /// типичной для всех. Данная абстракция делается для того, 
    /// чтобы уменьшить зависимость модуля от какого-либо 
    /// устройства рендеринга. При этом появляется возможность 
    /// параллельного развития данного модуля и Graphics API (GAPI) 
    /// стороннего разработчика (изменения в конкретном GAPI 
    /// не сказываются на коде модуля, за исключением реализации 
    /// данного устройства для данного модуля). Также появляется 
    /// возможность поддерживать сразу несколько устройств рендеринга. 
    /// К минусам можно отнести некоторую неизбежную потерю 
    /// производительности в первую очередь на конвертацию  
    /// типов модуля в типы конкретного GAPI и обратно, а также 
    /// невозможность использовать специфичные функции конкретного GAPI.
    /// Функциональность, предоставляемая интерфейсом, нацелена, 
    /// прежде всего, на программируемый конвейер (programmable pipeline). 
    /// Некоторые логические блоки вынесены в отдельные интерфейсы, 
    /// которые агрегируются в данном интерфейсе. Таким образом 
    /// для того, чтобы добавить реализацию нового GAPI в модуль, 
    /// необходимо добавить реализацию интерфейса IDevice, 
    /// а также интерфейсов, которых он агрегирует.
    /// </summary>
    public interface IDevice : IDisposable
    {
        #region Events

        /// <summary>
        /// Event occures when device is needing to 
        /// render its content (for ex., when 
        /// inner buffer has changed size)
        /// </summary>
        //event EventHandler RenderRequest;

        #endregion

        #region Properties

        /// <summary>
        /// Разреашающая способность внутреннего буфера
        /// </summary>
        Size Resolution { get; set; }

        /*/// <summary>
        /// Is device available?
        /// </summary>
        bool IsAvailable { get; }*/

        /// <summary>
        /// Цвет для очистки буфера
        /// </summary>
        Color DefaultColor { get; set; }

        /// <summary>
        /// Значение используемое для очистки z-буфера
        /// </summary>
        double DefaultDepth { get; set; }

        /// <summary>
        /// Текстура, куда осуществляеся вывод кадра
        /// </summary>
        RenderTarget RenderTarget { get; set; }

        /*/// <summary>
        /// Shader compiler
        /// </summary>
        IShaderCompiler ShaderCompiler { get; }*/

        #endregion

        #region Shading

        /// <summary>
        /// Finds the parameter by semantic name
        /// </summary>
        /// <param name="shader">Shader</param>
        /// <param name="semantic">Semantic</param>
        /// <returns>Parameter name or null if the parameter is not found</returns>
        string GetParameterBySemantic(Shader shader, string semantic);

        /// <summary>
        /// Sets value to the given parameter of a shader
        /// </summary>
        /// <param name="shader">A shader</param>
        /// <param name="name">Name of a parameter</param>
        /// <param name="value">Value</param>
        void SetShaderParameter(Shader shader, string name, bool value);

        /// <summary>
        /// Sets value to the given parameter of a shader
        /// </summary>
        /// <param name="shader">A shader</param>
        /// <param name="name">Name of a parameter</param>
        /// <param name="value">Value</param>
        void SetShaderParameter(Shader shader, string name, bool[] value);
        
        /// <summary>
        /// Sets value to the given parameter of a shader
        /// </summary>
        /// <param name="shader">A shader</param>
        /// <param name="name">Name of a parameter</param>
        /// <param name="value">Value</param>
        void SetShaderParameter(Shader shader, string name, float value);
        
        /// <summary>
        /// Sets value to the given parameter of a shader
        /// </summary>
        /// <param name="shader">A shader</param>
        /// <param name="name">Name of a parameter</param>
        /// <param name="value">Value</param>
        void SetShaderParameter(Shader shader, string name, float[] value);
        
        /// <summary>
        /// Sets value to the given parameter of a shader
        /// </summary>
        /// <param name="shader">A shader</param>
        /// <param name="name">Name of a parameter</param>
        /// <param name="value">Value</param>
        void SetShaderParameter(Shader shader, string name, int value);
        
        /// <summary>
        /// Sets value to the given parameter of a shader
        /// </summary>
        /// <param name="shader">A shader</param>
        /// <param name="name">Name of a parameter</param>
        /// <param name="value">Value</param>
        void SetShaderParameter(Shader shader, string name, int[] value);
        
        /// <summary>
        /// Sets value to the given parameter of a shader
        /// </summary>
        /// <param name="shader">A shader</param>
        /// <param name="name">Name of a parameter</param>
        /// <param name="value">Value</param>
        void SetShaderParameter(Shader shader, string name, Texture value);
        
        /// <summary>
        /// Sets value to the given parameter of a shader
        /// </summary>
        /// <param name="shader">A shader</param>
        /// <param name="name">Name of a parameter</param>
        /// <param name="value">Value</param>
        void SetShaderParameter(Shader shader, string name, Color value);
        
        /// <summary>
        /// Sets value to the given parameter of a shader
        /// </summary>
        /// <param name="shader">A shader</param>
        /// <param name="name">Name of a parameter</param>
        /// <param name="value">Value</param>
        void SetShaderParameter(Shader shader, string name, Color[] value);
        
        /// <summary>
        /// Sets value to the given parameter of a shader
        /// </summary>
        /// <param name="shader">A shader</param>
        /// <param name="name">Name of a parameter</param>
        /// <param name="value">Value</param>
        void SetShaderParameter(Shader shader, string name, Matrix4 value);
        
        /// <summary>
        /// Sets value to the given parameter of a shader
        /// </summary>
        /// <param name="shader">A shader</param>
        /// <param name="name">Name of a parameter</param>
        /// <param name="value">Value</param>
        void SetShaderParameter(Shader shader, string name, Matrix4[] value);
        
        /// <summary>
        /// Sets value to the given parameter of a shader
        /// </summary>
        /// <param name="shader">A shader</param>
        /// <param name="name">Name of a parameter</param>
        /// <param name="value">Value</param>
        void SetShaderParameter(Shader shader, string name, Vector4 value);
        
        /// <summary>
        /// Sets value to the given parameter of a shader
        /// </summary>
        /// <param name="shader">A shader</param>
        /// <param name="name">Name of a parameter</param>
        /// <param name="value">Value</param>
        void SetShaderParameter(Shader shader, string name, Vector3 value);
        
        /// <summary>
        /// Sets value to the given parameter of a shader
        /// </summary>
        /// <param name="shader">A shader</param>
        /// <param name="name">Name of a parameter</param>
        /// <param name="value">Value</param>
        void SetShaderParameter(Shader shader, string name, Vector4[] value);

        #endregion

        #region Rendering

        /// <summary>
        /// Begins rendering
        /// </summary>
        void Begin();

        /// <summary>
        /// Ends rendering
        /// </summary>
        void Present();

        /// <summary>
        /// Очистка заднего буфера
        /// </summary>
        void Clear();

        /// <summary>
        /// Очистка только буфера глубины
        /// </summary>
        void ClearDepth();

        /// <summary>
        /// Очистка только цвета пикселей
        /// </summary>
        void ClearFrame();

        
        /// <summary>
        /// Draws a polygonal object
        /// </summary>
        /// <param name="polygonal">A polygonal object</param>
        /// <param name="shader">A shader</param>
        void Draw(Polygonal polygonal, Shader shader);

        /*/// <summary>
        /// Отрисовка полигонов, находящихся в вершинном буфере
        /// </summary>
        /// <param name="startVertex">Вершина первого примитива</param>
        /// <param name="primitiveCount">Количество примитивов</param>
        void Draw(int startVertex, int primitiveCount);

        /// <summary>
        /// Отрисовка полигонов, используя индексный буфер
        /// </summary>	
        /// <param name="baseIndex">Базовый индекс (realIndex = Index + baseIndex)</param>	
        /// <param name="minVertex">Минимальная вершина</param>
        /// <param name="numVertices">Количество вершин</param>
        /// <param name="startIndex">Начальный индекс</param>		
        /// <param name="primitiveCount">Количество примитовов</param>
        void DrawIndexed(int baseIndex, int minVertex, int numVertices, int startIndex, int primitiveCount);*/

        #endregion
    }
}
